using MultiAgentsClient.ChatDataStructures;
using MultiAgentsClient.Service;
using MultiAgentsShared;
using Newtonsoft.Json.Linq;
using static System.Runtime.InteropServices.JavaScript.JSType;

namespace MultiAgentsClient.Manager;

public class LocalDataOperator : ManagerBase
{
    private readonly UserDataModel userDataModel;
    private readonly SqliteService sqliteService;

    #region events
    // recieve command from UI
    public record GetUserSettingsCommand();
    public record UpdateUserSettingsCommand(Dictionary<string, string> Settings);

    // send command to UI
    public record GetUserSettingsCompleteCommand(Dictionary<string, string> Settings);
    public record UpdateUserSettingsCompleteCommand();
    #endregion

    private enum SqliteTable
    {
        BasicSettings,
        BasicSettingsData,
        SessionData,
    }

    public enum BasicUserSettings
    {
        IsRememberRoomModel,
    }

    public enum BasicUserSettingsData
    {
        RoomModel,
    }

    public enum SessionData
    {
        UserName,
        Password,
        ServerName,
        SessionId,
    }

    public LocalDataOperator(
        UserDataModel userDataModel,
        SqliteService sqliteService)
    {
        this.userDataModel = userDataModel;
        this.sqliteService = sqliteService;

        eventBus.Subscribe<GetUserSettingsCommand>(cmd => { Task.Run(() => GetUserSettingsCommandHandler(cmd)); });
        eventBus.Subscribe<UpdateUserSettingsCommand>(cmd => { Task.Run(() => UpdateUserSettingsCommandHandler(cmd)); });
    }

    public string? GetUserSettings(BasicUserSettings setting)
    {
        Dictionary<string, string> settings = sqliteService.GetDictionary(userDataModel.Id, SqliteTable.BasicSettings.ToString());

        settings.TryGetValue(setting.ToString(), out string? targetSetting);

        return targetSetting;
    }

    public void UpdateUserSettingsData(BasicUserSettingsData data, string value)
    {
        sqliteService.UpdateDictionaryValue(userDataModel.Id, SqliteTable.BasicSettingsData.ToString(), data.ToString(), value);
    }

    public string GetUserSettingsData(BasicUserSettingsData data)
    {
        Dictionary<string, string> settingsData = sqliteService.GetDictionary(userDataModel.Id, SqliteTable.BasicSettingsData.ToString());

        settingsData.TryGetValue(data.ToString(), out string? targetData);

        if (targetData == null)
        {
            throw Debug.ShouldNotHappen();
        }

        return targetData;
    }

    public Dictionary<string, string> GetLoginInformation()
    {
        Dictionary<string, string> sessionData = sqliteService.GetDictionary(0, SqliteTable.SessionData.ToString());

        return sessionData;
    }

    public void ClearLoginInformation()
    {
        sqliteService.ClearTable(0, SqliteTable.SessionData.ToString());
    }

    public bool SaveLoginInformation(string userName, string password, string serverName, string sessionId)
    {
        sqliteService.UpdateDictionaryValue(0, SqliteTable.SessionData.ToString(), SessionData.UserName.ToString(), userName);
        sqliteService.UpdateDictionaryValue(0, SqliteTable.SessionData.ToString(), SessionData.Password.ToString(), password);
        sqliteService.UpdateDictionaryValue(0, SqliteTable.SessionData.ToString(), SessionData.ServerName.ToString(), serverName);
        sqliteService.UpdateDictionaryValue(0, SqliteTable.SessionData.ToString(), SessionData.SessionId.ToString(), sessionId);

        return true;
    }

    #region command 
    public ValueTask GetUserSettingsCommandHandler(GetUserSettingsCommand _)
    {
        Dictionary<string, string> settings = sqliteService.GetDictionary(userDataModel.Id, SqliteTable.BasicSettings.ToString());
        eventBus.Publish(new GetUserSettingsCompleteCommand(settings));

        return ValueTask.CompletedTask;
    }

    public ValueTask UpdateUserSettingsCommandHandler(UpdateUserSettingsCommand cmd)
    {
        foreach (KeyValuePair<string, string> setting in cmd.Settings)
        {
            sqliteService.UpdateDictionaryValue(userDataModel.Id, SqliteTable.BasicSettings.ToString(), setting.Key, setting.Value);
        }
        
        eventBus.Publish(new UpdateUserSettingsCompleteCommand());

        return ValueTask.CompletedTask;
    }
    #endregion
}
